<html>
<head>
<title>CpcPaChi - Version 0.08</title>
<style type="text/css">
span {
	font-family: 'Courier New';
	font-size: 10pt;
	color: #000000;
}
.sc0 {
	color: #808080;
}
.sc3 {
	color: #008080;
}
.sc4 {
	color: #FF8000;
}
.sc5 {
	font-weight: bold;
	color: #0000FF;
}
.sc7 {
	color: #808080;
}
.sc9 {
	color: #804000;
}
.sc10 {
	font-weight: bold;
	color: #000080;
}
.sc11 {
}
</style>
</head>
<body>
<h2>Un compilador sencillo paso a paso (9 - Acercamiento a las variables)</h2>

<p align="right">(Volver al <a href="doc.html">&iacute;ndice</a>) </p>

<p>Ya hab&iacute;amos preparado una primera tabla de s&iacute;mbolos, que nos permit&iacute;a  utilizar constantes en los programas. Ahora vamos a ampliar ligeramente la estructura para permitir el manejo b&aacute;sico de variables.</p>

<p>De cada s&iacute;mbolo est&aacute;bamos guardando el nombre, el tipo (por ahora s&oacute;lo byte) y el valor. En un principio, nos podr&iacute;a bastar para un manejo b&aacute;sico de variables a nuesto nivel. Aun as&iacute;, hay otra diferencia entre el manejo de constantes y variables: una constante se declara a la vez que se le da un valor, pero una variable no: primero se declara y luego se le da un valor. Esto puede provocar que intentemos usar una variable que se ha declarado pero que todav&iacute;a no tiene un valor. Hay tres formas de atacar este problema: </p>
<ul>
  <li>Ignorarlo, con lo cual se podr&aacute; acceder al valor de una variable a la que realmente no se ha dado valor, y que contendr&aacute; basura. Es lo que se suele hacer e los compiladores de C. </li>
<li>Dar un valor a las variables cuando se declaren. Por ejemplo, se podr&iacute;a dar por sentado que una variable num&eacute;rica tendr&aacute; un valor inicial de cero. Es lo que se suele hacer en muchas versiones de Basic. </li>
<li>Anotar si se ha dado un valor a la variable o no, y mostrar un mensaje de error si se intenta usar una variable que no tiene valor. En el momento de compilar se puede hacer una primera estimaci&oacute;n, y avisar de los posibles errores, como se hace en Java, pero la mayor&iacute;a de comprobaciones &quot;reales&quot; habr&iacute;a que hacerlas en tiempo de ejecuci&oacute;n.</li>
</ul>
<p>Yo seguir&eacute; la primera aproximaci&oacute;n: reservar&eacute; un espacio para cada variable, no le dar&eacute; un valor incial, y no comprobar&eacute; si la variable ten&iacute;a valor cuando se acceda a ella.</p>
<p>Habr&aacute; que modificar la tabla de s&iacute;mbolos ligeramente, porque de las variables no guardaremos su valor actual, sino la direcci&oacute;n de memoria en que se encuentran.</p>
<p>Tambi&eacute;n habr&aacute; que ampliar ligeramente el analizador l&eacute;xico: ahora, adem&aacute;s del bloque CONST, podr&aacute; haber un bloque VAR, y ambos ser&aacute;n opcionales, por lo que esa parte del an&aacute;lisis sint&aacute;ctico podr&iacute;a ser:</p>
<pre><code>
  (* const o var, antes de begin *)<br>  repeat<br>  <br>    orden := upcase(obtenerIdentificador);<br>    if orden = 'CONST' then<br>      begin<br>      analizarCONST;<br>      end;<br>    <br>    if orden = 'VAR' then<br>      begin<br>      analizarVAR;<br>      end;<br>    <br>  until orden = 'BEGIN';  </code></pre>
<p>El an&aacute;lisis sint&aacute;ctico de la orden VAR ser&iacute;a muy parecido al de CONST:</p>
<pre><code>
  procedure analizarVAR;<br>var<br>  ident: string;<br>  tipoVar: string;<br>  terminador: char;<br>begin<br>  ident := upcase(obtenerIdentificador);<br>  { Despues del identificador podra ir :tipo o ,var }<br>  { De momento, solo una variable }<br>  leerSimbolo(':');<br>  tipoVar := upcase(obtenerIdentificador);<br>  if (tipoVar &lt;&gt; 'BYTE') then<br>    errorFatal('Tipo incorrecto');<br>  terminador := leerCualquierSimbolo;<br>  if (terminador &lt;&gt; ';') then<br>    errorFatal('Terminador incorrecto');<br>  insertarSimboloVar(ident, 'b');<br>end;<br></code></pre>
<p>Como se puede ver, ah&iacute; aparece una orden &quot;errorFatal&quot; que no exist&iacute;a antes. Es una peque&ntilde;a mejora al an&aacute;lisis l&eacute;xico: llevar cuenta de la l&iacute;nea y la columna en que estamos, para poder dar mensajes de error un poco m&aacute;s detallados. Reemplazar&aacute; a los WRITELN con mensajes de error seguidos de HALT que est&aacute;bamos usando hasta ahora :</p>

<pre><code>
(* Muestra un mensaje de error y abandona el programa *)<br>procedure errorFatal(mensaje: string);<br>begin<br>   write('Linea: ',lineaActual,'. Pos: ',posicionLineaActual+1,'. ');<br>   writeln(mensaje);<br>   halt;<br>end;<br></code></pre>


<p>La parte complicada del manejo de variables no es &eacute;sta, sino la que est&aacute; por llegar. Habr&aacute; que dar valores a variables, que se guardar&aacute;n en la posici&oacute;n de memoria que le hayamos reservado. Se deber&aacute; poder leer el valor de una variable. Se deber&aacute; poder hacer operaciones simples, como el incremento (INC) y el decremento (DEC). Eso lo haremos en el pr&oacute;ximo acercamiento. Otras operaciones m&aacute;s complejas, como las aritm&eacute;ticas y las comparaciones tardar&aacute;n un poco m&aacute;s en llegar...</p>
<p><br>
  Como siempre, para m&aacute;s detalles, todo el c&oacute;digo est&aacute; en la p&aacute;gina del proyecto en Google Code:<br />
  <br />
  <a href="http://code.google.com/p/cpcpachi/">http://code.google.com/p/cpcpachi/</a></p>
<p align="right">(Volver al <a href="doc.html">&iacute;ndice</a>) </p>
</body>
</html>
